10. System-Level IO {CSAPP}

aliases
No value
tags
No value
description
11장이 의존하는 필수개념들 짚고 넘어가자
title
10. System-Level IO {CSAPP}
created
2023-09-14T14:07:44
updated
2023-09-20T15:46:58

README

이 파일은 사실 11. Network Programming {CSAPP}, 웹 서버 만드는 데 필요한 RIO 패키지 때문에 넘어왔다. 파일 디스크립터와 입력출력에 대한 내용을 빠르게 짚고 바로 RIO 패키지 구현체로 넘어갈 것. 대충 봤는데 버퍼가 없어 빠르다고?

유닉스 세상에서 모든 것은 파일이다.

대학시절 교수님이 귀에 딱지가 앉도록 말씀하셨다. 그래서 파일을 어떻게 다루는지, file descriptor가 무엇인지, 파일 메타데이터를 어떻게 쓰는지 등등에 대한 내용을 Systems Programming {ssu2021-1st} 🐼 수업시간에 들었다.

mmap은 유닉스 세상에서 스위스 아미 나이프이다.

자세한 건 11. memory mapping and Copy-on-write (COW) {SP}에서 확인바람.

스크린샷 2023-09-14 오후 9.19.57.png800

10.5. Robust Reading and Writing with the RIO Package

두 가지 기능을 제공한다.

  1. Unbuffered Input & output: 애플리케이션 수준의 버퍼 없이 곧장 fd를 사용해 파일을 읽거나 쓸 수 있다.

    1. ssize_t rio_readn(int fd, void *usrbuf, size_t n);
    2. ssize_t rio_writen(int fd, void *usrbuf, size_t n);
    3. Returns: number of bytes transferred if OK, 0 on EOF (rio_readn only), −1 on error
  2. Buffered Input: thread safe한 버퍼기반 입력을 통해 오버헤드를 줄인다.

    1. ssize_t rio_readlineb(rio_t *rp, void *usrbuf, size_t maxlen);
    2. ssize_t rio_readnb(rio_t *rp, void *usrbuf, size_t n);
    3. Returns: number of bytes read if OK, 0 on EOF, −1 on error

void rio_readinitb(rio_t *rp, int fd);: rio 객체 초기화, file descriptor 필요.

read(2)

10.6. Readig File Metadata

stat(2) 참조

#include <unistd.h> 
#include <sys/stat.h> 
int stat(const char *filename, struct stat *buf); 
int fstat(int fd, struct stat *buf); 
// Returns: 0 if OK, −1 on error

struct stat *에 파일 메타데이터가 담긴다.

/* Metadata returned by the stat and fstat functions */ 
struct stat { 
	dev_t st_dev; /* Device */ 
	ino_t st_ino; /* inode */ 
	mode_t st_mode; /* Protection and file type */ 
	nlink_t st_nlink; /* Number of hard links */ 
	uid_t st_uid; /* User ID of owner */ 
	gid_t st_gid; /* Group ID of owner */ 
	dev_t st_rdev; /* Device type (if inode device) */ 
	off_t st_size; /* Total size, in bytes */ 
	unsigned long st_blksize; /* Block size for filesystem I/O */ 
	unsigned long st_blocks; /* Number of blocks allocated */ 
	time_t st_atime; /* Time of last access */ 
	time_t st_mtime; /* Time of last modification */ 
	time_t st_ctime; /* Time of last change */
};
그런데, 파일 메타데이터는 사용자가 임의대로 추가할 수 있는거 아니었음?

10.7. Read Directory Contents

#include <sys/types.h> 
#include <dirent.h> 
DIR *opendir(const char *name);
// Returns: pointer to handle if OK, NULL on error

directory stream의 첫번째 주소를 가리킨다. 해당 디렉토리 원소가 고갈될 때까지 readdir을 호출하면 다음 struct dirent * 포인터를 얻을 수 있다.

#include <dirent.h> 
struct dirent *readdir(DIR *dirp); 
// Returns: pointer to next directory entry if OK, NULL if no more entries or error

DIR * 객체를 닫을 경우 closedir을 호출하면 된다.

10.8. Sharing Files

I/O Redirection

아주 중요한 개념인 dup2에 대해서 나온다. 리눅스 셸에서는 >, 2>, <가 있다. 각각

  1. lhs > rhs: lhs의 stdout 출력 결과를 rhs파일로 리디렉션 하시오.
  2. lhs 2> rhs: lhs의 stderr 출력 결과를 rhs 파일로 리디렉션 하시오.
  3. lhs < rhs: rhs파일을 lhs의 stdin으로 리디렉션 하시오.
#include <unistd.h> 
int dup2(int oldfd, int newfd); 
// Returns: nonnegative descriptor if OK, −1 on error

descriptor table의 newfd번째 인덱스의 값을 oldfd의 값으로 덮어쓴다. 만약 newfd가 열려있다면 자동으로 닫는다.